/*
 *  $Id: Creature.cs 1233 2010-12-18 17:54:48Z thenn.erannor $
 *  This file is a part of Ragima CCG.
 *  (C) 2008-2010 Ragima development group.
 *
 *  Licensed under the terms of the GNU GPL License version 2.
 *
 */

using System;
using System.Collections.Generic;

using AgateLib;
using AgateLib.Geometry;

using Nereal.Serialization;

namespace Ragima {
    /// <summary>
    /// Тип цели: существо на поле.
    /// </summary>
    public class CreatureTarget : TargetType {
        /// <summary>
        /// Цель: союзное существо.
        /// </summary>
        public static readonly CreatureTarget Own = new CreatureTarget(new Languages.Phrase("target.creature.own"), true, false);
        /// <summary>
        /// Цель: вражеское существо.
        /// </summary>
        public static readonly CreatureTarget Enemy = new CreatureTarget(new Languages.Phrase("target.creature.enemy"), false, true);
        /// <summary>
        /// Цель: любое существо.
        /// </summary>
        public static readonly CreatureTarget Both = new CreatureTarget(new Languages.Phrase("target.creature.both"), true, true);
        /// <summary>
        /// Цель: место призыва поверх имеющегося существа.
        /// </summary>
        public static readonly CreatureTarget Summon = new CreatureTarget(new Languages.Phrase("target.creature.summon"), true, false);
        /// <summary>
        /// Цель: союзное существо, кроме существа-кастера (если цель для способности существа).
        /// </summary>
        public static readonly CreatureTarget OwnExceptSelf = new CreatureTarget(new Languages.Phrase("target.creature.own_except_self"), true, false, IsNotSelf);

        private bool _own, _enemy;
        private TargetPredicate<Creature> _condition;

        public CreatureTarget(Languages.Phrase notice, bool own, bool enemy) : this(notice, own, enemy, null) {
        }
        public CreatureTarget(Languages.Phrase notice, bool own, bool enemy, TargetPredicate<Creature> condition) : base(notice) {
            _own = own;
            _enemy = enemy;
            _condition = condition;
        }

        public override bool IsRealTarget {
            get { return true; }
        }

        /// <summary>
        /// Число целей равно числу существ на поле.
        /// </summary>
        public override int GetCount(AbstractObject caster) {
            int count = 0;
            if (_own)
                count += caster.Owner.GetCreatureCount();
            if (_enemy)
                count += caster.Owner.Enemy.GetCreatureCount();
            return count;
        }

        /// <summary>
        /// Целевые регионы: существа на поле (без антимагии).
        /// </summary>
        public override bool AcceptRegion(Region region) {
            var pcr = region as PlayerCreatureRegion;
            if (pcr == null)
                return false;
            if (!(pcr.IsEnemy ? _enemy : _own))
                return false;
            if (pcr.Creature.HasFlag<Affects.Antimagic>())
                return false;
            if (_condition != null && !_condition(Request, pcr.Creature))
                return false;
            return true;
        }

        public override TargetArgs GetArgs(Region region) {
            var pcr = region as PlayerCreatureRegion;
            return pcr != null ? new CreatureTargetArgs(Request.Player, Request.Caster, pcr.Creature) : null;
        }

        /// <summary>
        /// Условие на существо: не сам кастер.
        /// </summary>
        public static bool IsNotSelf(TargetRequest request, Creature creature) {
            return creature != request.Caster;
        }

        /// <summary>
        /// Условие на существо: не дух.
        /// </summary>
        public static bool IsNotSpirit(TargetRequest request, Creature cr) {
            return !cr.IsSpirit;
        }

        /// <summary>
        /// Условие на существо: не нежить.
        /// </summary>
        public static bool IsNotUndead(TargetRequest request, Creature cr) {
            return !cr.IsUndead;
        }

        /// <summary>
        /// Условие на существо: живое.
        /// </summary>
        public static bool IsLiving(TargetRequest request, Creature cr) {
            return !(cr.IsUndead || cr.IsSpirit);
        }

        /// <summary>
        /// Условие на существо: отдыхающее.
        /// </summary>
        public static bool IsDisabled(TargetRequest request, Creature cr) {
            return cr.Disabled;
        }

        /// <summary>
        /// Условие на существо: не отдыхающее.
        /// </summary>
        public static bool IsNotDisabled(TargetRequest request, Creature cr) {
            return !cr.Disabled;
        }

        /// <summary>
        /// Условие на существо: святое.
        /// </summary>
        public static bool IsHoly(TargetRequest request, Creature cr) {
            return cr.IsHoly;
        }

        /// <summary>
        /// Условие на существо: не святое.
        /// </summary>
        public static bool IsNotHoly(TargetRequest request, Creature cr) {
            return !cr.IsHoly;
        }

        /// <summary>
        /// Условие на существо: подводное.
        /// </summary>
        public static bool IsAquatic(TargetRequest request, Creature cr) {
            return cr.IsAquatic;
        }
    }

    [TypeId("creature")]
    public class CreatureTargetArgs : TargetArgs<Creature> {
        [Serialize, XmlName("target"), Reference(true, typeof(string), Serialization.Resolvers.GameCreature)]
        private Creature _target;

        public CreatureTargetArgs() {
        }
        public CreatureTargetArgs(Player player, AbstractObject caster, Creature target) : base(player, caster) {
            _target = target;
        }

        public override Creature Target {
            get { return _target; }
        }
    }
}
